Exec Exec stà per System Executive vale a dire Sistema Esecutivo che, come si può intuire dal nome si occupa di gestire completamentamente la macchina; l'exec.library mette a disposizione una serie di funzioni per sfruttare l'exec (creazione di task, interrupt, comunicazioni ecc.); dato che queste operazioni sono molto importanti e che verranno utilizzate molto spesso, è giusto che vengano analizzate quì, prima di entrare nel vivo della programmazione su Amiga. La prima caratteristica da analizzare è l'allocazione dinamica della memoria; dato che l'Amiga è un sistema Multitasking e che tutte le strutture gestite sono dinamiche (cioè possono venire allocate e utilizzate in un qualsiasi momento) non si può pretendere che i programmi o i dati vengano a trovarsi in indirizzo fissi di memoria (dato che in quello spazio potrebbe essere presente un qualsiasi altro dato, creato da un altro programma), per cui ogni qualvolta che necessita utilizzare memoria occorre chiederla al sistema operativo il quale, tramite una lista interna provvederà ad allocarne la quantità richiesta e a fornirne l'indirizzo. Vi è un altro modo per allocare spazi di memoria da utilizzare nei programmi: tramite la dichiarazione delle variabili del C; si badi bene però che questo corrisponde a spazio fisico occupato dal codice, per cui se si dichiara un vettore di 250K, l'eseguibile sarà allungato di appunto 250K introducendo così, un'inutile spreco di spazio su supporto magnetico. La funzione dell'exec.library che si occupa dell'allocazione di memoria è AllocMem ed ha la seguente sintassi: BloccoMem = AllocMem(NumBytes,attributi); Dove 'NumBytes' indica la lunghezza in bytes del blocco di memoria; 'attributi' indicano che tipo di memoria allocare e come deve essere allocata; 'attributi' può valere: MEMF_CHIP, indica che il tipo di memoria deve essere CHIP MEMF_FAST, la memoria deve essere FAST MEMF_ANY, la memoria può essere di qualsiasi tipo, in tal caso avrà precedenza la FAST, se questa non fosse disponibile si provvederà per la CHIP MEMF_PUBLIC, questo flag indica che la memoria è di tipo pubblico può cioè, essere condivisa fra più task (questa caratteristica non è ancora implementata, il flag è stato inserito per usi futuri) MEMF_CLEAR, utilizzando questo flag si cancella tutto il blocco di memoria prima che venga messo a disposizione del programma MEMF_24BITDMA, (dalla verione 37 del S.O.) indica che il blocco di memoria verrà allocato nei primi 24 bit di indirizzo; questo poiché alcune schede Zorro II (che supporta solo 24 bit indirizzo perché creato con A2000 che sfruttava tali bit a causa del 68000) potrebbero fare uso di memoria e quindi non possono "vedere" memoria al di fuori dei succitati 24 bit. MEMF_REVERSE (V37), dato che nella ricerca del blocco di memoria richiesto si procede a partire dagli indirizzi più bassi, attivando questo flag si procede dall'indirizzo più alto (le applicazioni che si osservano sovente sono i caricatori dei S.O. in RAM che selezionano l'indirizzo più alto) vi sono altri flag meno importanti per i quali si rimanda ai doc delle funzioni; 'BloccoMem' è il puntatore al blocco di memoria allocato ritornato dalla funzione, o NULL se non è stato possibile allocare il blocco, per cui ricordatevi di controllare sempre il valore restituito da tale funzione; vi assicuro che scrivere dati all'indirizzo 0 che corrisponde a NULL, porta probabilmente al cosiddetto GURU pittoresco riconoscibile non dalla solita scritta lampeggiante, ma da una serie di effetti video colorati (un Amiga si deve riconoscere anche quando si blocca); esempi: UBYTE *buffer; . . if ((buffer = (UBYTE *)AllocMem(10000,MEMF_CLEAR)) == NULL) printf("Errore non posso allocare buffer\n"); /* Alloca 10000 bytes di qualsiasi tipo e cancellali */ . if ((buffer = (UBYTE *)AllocMem(5000,MEMF_CHIP|MEMF_CLEAR)) == NULL) printf("Errore non posso allocare buffer\n"); /* Alloca 5000 bytes di memoria chip con cancellazione */ In entrambi gli esempi se non è possibile allocare i buffer verrà segnalato errore; ovviamente non bisogna indicare contemporaneamente flag in conflitto come MEMF_CHIP e MEMF_FAST. E qui si reincontra la prima regola dell'Amiga: "tutto ciò che viene allocato dovrà essere deallocato" per cui eccovi la funzione di exec che vi permette di resituire al sistema il blocco di memoria allocato, una volta che non ne avete più bisogno: FreeMem(BloccoMem,NumBytes); 'BloccoMem' è il puntatore al blocco restituito da AllocMem e NumBytes la lunghezza di quest'ultimo in bytes; attenzione a non fornire un numero diverso da quello utilizzato per l'allocazione, non fornire un puntatore errato o non tentare di deallocare due volte lo stesso buffer, altrimenti andrete incontro ad un guru; esempio: FreeMem(buffer,10000); /* Deallocazione del buffer del primo esempio */ Dalla V36 del s.o. è disponibile una funzione di allocazione e una di deallocazione della memoria che ricorda la lunghezza del blocco allocato, per cui non vi è bisogno di indicarlo nella liberazione di quest'ultimo; il funzionamento di queste funzioni è identico alle corrispettive già esaminate: BloccoMem = AllocVec(NumBytes,attributi); FreeVec(BloccoMem); Non tentate di utilizzare AllocMem con FreeVec o viceversa riguardo ad uno stesso blocco; ad una AllocMem deve corrispondere una FreeMem e ad una AllocVec una FreeVec. Vi sono altre funzioni per la gestione della memoria come conoscere la quantità disponibile o altre che potrete trovare nei doc.